package com.shanxia.codec.cmd;

import com.shanxia.codec.ProtocolDataBase;
import com.shanxia.codec.enums.DecodeEnum;
import lombok.Data;

import java.util.Arrays;
import java.util.Objects;

import static com.shanxia.codec.Decoder.*;

/**
 * S -> C
 * 后台服务器下发充电桩字符型参数
 * 后台服务器向充电桩下发充电桩字符形参数命令
 */
@Data
public class Cmd3 extends ProtocolDataBase {

    public static final int MIN_SIZE = 11;

    private int v1;
    private int v2;
    private int type;                         // 类型 [0-查询/ /1-设置]
    private int paramAddr;                    // 设置/查询参数起始地址
    private int paramBytes;                   // 设置参数字节数
    private String data;                      // 设置数据

    public Cmd3(){
        super.setCmd(3);
    }

    public static Cmd3 decodeFromBase(ProtocolDataBase protocolDataBase) {
        Cmd3 cmd = new Cmd3();
        cmd.copyDataFrom(protocolDataBase);
        byte[] dataField = protocolDataBase.getDataField();
        if (dataField.length < MIN_SIZE) {
            cmd.setResult(DecodeEnum.InvalidData);
            return cmd;
        }
        int offset = 0;
        cmd.v1 = getUint16(dataField, offset);
        offset += 2;
        cmd.v2 = getUint16(dataField, offset);
        offset += 2;
        // 1字节类型
        cmd.type = getUint8(dataField[offset++]);
        // 4字节设置/查询参数启始地址
        cmd.paramAddr = bytesToIntLittle(dataField, offset);
        offset += 4;
        // 2字节设置参数字节数
        cmd.paramBytes = getUint16(dataField, offset);
        offset += 2;
        // N字节设置数据
        if (Objects.equals(cmd.type, 1)) {
            switch (cmd.paramAddr) {
                // 8字节标准时钟时间
                case 2:
                    cmd.data = getStandardTime(dataField, offset);
                    break;
                // 32字节充电桩编码
                case 1:
                // 8字节管理员密码
                case 3:
                // 8字节操作员密码
                case 4:
                // 6字节MAC地址
                case 5:
                // 16字节桩登入服务器密码  TODO 确认密码转换是否准确 ?-sy
                case 6:
                // 256字节桩主界面二维码
                case 7:
                // 16字节客户服务热线 1
                case 8:
                // 16字节客户服务热线 2
                case 9:
                // 256字节用户支付二维码
                case 10:
                // 128字节桩主界面二维码前缀
                case 11:
                // 12字节DLT645-2007 电表地址
                case 12:
                // 64字节云服务器域名
                case 13:
                    cmd.data = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + cmd.paramBytes), true);
                    break;
                default:
                    break;
            }
        }
        return cmd;
    }

    @Override
    public byte[] getDataField() {
        int offset = 0;
        byte[] buf = new byte[MIN_SIZE + this.paramBytes];
        getBytesAsUint16(buf, offset, this.v1);
        offset += 2;
        getBytesAsUint16(buf, offset, this.v2);
        offset += 2;
        buf[offset++] = (byte) this.type;
        intToBytesLittle(buf, 5, this.paramAddr);
        offset += 4;
        getBytesAsUint16(buf, 9, this.paramBytes);
        offset += 4;
        if (Objects.equals(this.type, 1)) {
            // 数据域转换  得根据不同得结果来转换
            switch (this.paramAddr) {
                // 标准时钟时间
                case 2:
                    encodeBasicTime(data, buf, offset, true);
                    break;
                // 充电桩编码
                case 1:
                // 管理员密码
                case 3:
                    // 操作员密码
                case 4:
                    // MAC地址
                case 5:
                    // 桩登入服务器密码  TODO 确认密码转换是否准确
                case 6:
                    // 桩主界面二维码
                case 7:
                    // 客户服务热线 1
                case 8:
                    // 客户服务热线 2
                case 9:
                    // 用户支付二维码
                case 10:
                    // 桩主界面二维码前缀
                case 11:
                    // DLT645-2007 电表地址
                case 12:
                    // 云服务器域名
                case 13:
                    encodeAscii(buf, this.data, this.paramBytes, offset);
                    break;
                default:
                    break;
            }
        }
        return buf;
    }
}